package com.my12306.train.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.my12306.common.constant.CommonConstants;
import com.my12306.common.model.vo.PageVo;
import com.my12306.common.util.PageUtils;
import com.my12306.common.util.SnowflakeIdWorker;
import com.my12306.common.util.response.ResponseData;
import com.my12306.train.constant.MileageType;
import com.my12306.train.dao.MileageDao;
import com.my12306.train.model.entity.MileageEntity;
import com.my12306.train.model.entity.RouteEntity;
import com.my12306.train.model.entity.StationEntity;
import com.my12306.train.model.vo.MileageRouteVo;
import com.my12306.train.model.vo.MileageVo;
import com.my12306.train.service.MileageService;
import com.my12306.train.service.RouteService;
import com.my12306.train.service.StationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;


@Service("mileageService")
public class MileageServiceImpl extends ServiceImpl<MileageDao, MileageEntity> implements MileageService {
    @Autowired
    private StationService stationService;
    @Autowired
    private RouteService routeService;

    /**
     * 分页查询里程
     *
     * @param pageVo
     * @return
     */
    @Override
    public PageUtils queryMileageByPage(PageVo pageVo) {
        pageVo.init();
        System.out.println(pageVo);
        List<MileageVo> datalist = this.baseMapper.queryMileageByPage(pageVo, CommonConstants.LogicDelete.no_delet.getValue());
        if (datalist != null) {
            int dataCount = this.queryMileageCountByPage(pageVo, CommonConstants.LogicDelete.no_delet.getValue());
            PageUtils page = PageUtils.build(pageVo, datalist, dataCount);
            return page;
        }
        return null;
    }

    /**
     * 查询分页总数据量
     *
     * @param pageVo      分页模型(内含相关查条件)
     * @param logicDelete (逻辑删除字段)
     * @return
     */
    @Override
    public Integer queryMileageCountByPage(PageVo pageVo, int logicDelete) {
        return this.baseMapper.queryMileageCount(pageVo, logicDelete);
    }

    /**
     * 添加一条线路的时刻表
     *
     * @param mileageRouteVo
     * @return
     */
    @Override
    @Transactional
    public Long saveMileage(MileageRouteVo mileageRouteVo) {
        @NotNull List<MileageEntity> mileageList = mileageRouteVo.getMileageList();
        @NotNull Long routeId = mileageRouteVo.getRouteId();
        Long startId = mileageList.get(0).getFromId();
        Long endId = mileageList.get(mileageList.size() - 1).getToId();
        System.out.println("mileageList========>"+mileageList);
        System.out.println("mileageRouteVo==========>"+mileageRouteVo);
        //计算总里程
        Double sumMileage = mileageList.parallelStream().map(x -> {
            return x.getTotalMileage();
        }).reduce(0.0, Double::sum);
        //构建 起始站-》终点站的mileage 并且设置parentId=-1
        MileageEntity mileage = new MileageEntity.MielageBuilder()
                .parentId(-1L)
                .mileageId(SnowflakeIdWorker.generateId())
                .routeId(routeId)
                .totalMileage(sumMileage)
                .createDate(new Date())
                .updateDate(new Date())
                .builder();

        AtomicLong parentId = new AtomicLong(mileage.getMileageId());
        List<MileageEntity> mileages = new ArrayList<>();
        //两条以上数据就需要进行处理
            mileages = mileageList.stream().map(x -> {
                QueryWrapper<StationEntity> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("station_id", x.getFromId()).eq("logic_delete", CommonConstants.LogicDelete.no_delet.getValue());
//            StationEntity entity = stationService.getBaseMapper().selectOne(queryWrapper);
                String fromName = Optional.ofNullable(stationService.getBaseMapper().selectOne(queryWrapper)).orElse(new StationEntity()).getStationName();
                x.setFromName(fromName);
                QueryWrapper<StationEntity> query = new QueryWrapper<>();
                System.out.println(x.getToId());
                query.eq("station_id", x.getToId()).eq("logic_delete", CommonConstants.LogicDelete.no_delet.getValue());
//            StationEntity stationEntity = stationService.getBaseMapper().selectOne(query);
                String toName = Optional.ofNullable(stationService.getBaseMapper().selectOne(query)).orElse(new StationEntity()).getStationName();
                x.setToName(toName);
                x.setMileageId(SnowflakeIdWorker.generateId());
                x.setParentId(parentId.getAndSet(x.getMileageId()));
                x.setRouteId(routeId);
                //做特殊处理如果只有一条数据就直接把父id置为-1
                if (mileageList.size() == 1 || x.getFromId().equals(startId) && x.getToId().equals(endId)) {

                    x.setMileageType(MileageType.start_end.getValue());
                    x.setParentId(-1L);
                } else if (x.getFromId().equals(startId)) {
                    x.setMileageType(MileageType.start_after.getValue());
                } else if (x.getToId().equals(endId)) {
                    x.setMileageType(MileageType.after_end.getValue());
                } else {
                    x.setMileageType(MileageType.after_after.getValue());
                }
                x.setCreateDate(new Date());
                x.setUpdateDate(new Date());
                return x;
            }).distinct().collect(Collectors.toList());
        //只有要数据大于1就需要添加一条 起始站和终点站
        if (mileageList!=null&&mileageList.size() > 1) {
            MileageEntity ft = mileages.get(0);
            MileageEntity fn = mileages.get(mileages.size() - 1);
            mileage.setFromId(ft.getFromId());
            mileage.setFromName(ft.getFromName());
            mileage.setToId(fn.getToId());
            mileage.setToName(fn.getToName());
            mileage.setMileageType(MileageType.start_end.getValue());
            mileages.add(mileage);
        }
        System.out.println(mileages);
        if (mileages!=null&&mileages.size()>0) {
            this.baseMapper.saveBatchMileage(mileages);
            return 1L;
        }
        return null;
    }

    /**
     * 修改里程
     * 1.修改本身
     * 2.比较左右是否发生修改，如果发生修改则找出对应的上一段里程或者下一段里程
     *
     * @param mileage
     */
    @Override
    @Transactional
    public void updateMileageById(MileageEntity mileage) {
        MileageEntity mileageVo = this.queryMileageByMileageId(mileage.getMileageId(), CommonConstants.LogicDelete.no_delet.getValue());
        if (mileageVo != null) {
            int mileageType = mileageVo.getMileageType();
            //如果左边先等证明左边没被修改
            boolean left = mileage.getFromId().equals(mileageVo.getFromId());
            //如果右边相等则右边没被修改
            boolean right = mileage.getToId().equals(mileageVo.getToId());
            double totalMileage = mileage.getTotalMileage()-mileageVo.getTotalMileage();
            System.out.println("left:"+left+",right:"+right);
            //查出修改from的车站即上一段里程的to的车站
            StationEntity toStation = null;
            if (!left) {
                toStation = stationService.queryStationById(mileage.getFromId());
                System.out.println("左边车站："+toStation);
            }
            //查出修改to的车站即下一段里程的from的车站
            StationEntity fromStation = null;
            if (!right) {
                fromStation = stationService.queryStationById(mileage.getToId());
                System.out.println("右边车站："+fromStation);
            }

            mileage.setUpdateDate(new Date());
            //修改本身的车站名称
            if (fromStation != null || toStation != null) {
                if (fromStation!=null) {
                    mileage.setToName(fromStation.getStationName());
                }else{
                    mileage.setFromName(toStation.getStationName());
                }
                this.baseMapper.updateById(mileage);
                //如果左边改变修改上一段的to区域
                QueryWrapper<MileageEntity> wrapper = new QueryWrapper<>();
                wrapper.eq("to_id", mileageVo.getFromId());
                wrapper.eq("route_id", mileageVo.getRouteId())
                        .eq("logic_delete", CommonConstants.LogicDelete.no_delet.getValue());

                MileageEntity toEntity = this.baseMapper.selectOne(wrapper);
                if (toEntity != null&&toStation!=null) {
                    toEntity.setUpdateDate(new Date());
                    toEntity.setToId(toStation.getStationId());
                    toEntity.setToName(toStation.getStationName());
                    this.baseMapper.updateById(toEntity);
                }
                //如果右边改变，修改下一段的from区域
                wrapper=new QueryWrapper<>();
                wrapper.eq("from_id", mileageVo.getToId());
                wrapper.eq("route_id", mileageVo.getRouteId())
                        .eq("logic_delete", CommonConstants.LogicDelete.no_delet.getValue());
                MileageEntity fromEntity = this.baseMapper.selectOne(wrapper);
                if (fromEntity != null&&fromStation!=null) {
                    fromEntity.setUpdateDate(new Date());
                    fromEntity.setFromId(fromStation.getStationId());
                    fromEntity.setFromName(fromStation.getStationName());
                    this.baseMapper.updateById(fromEntity);
                }
                //如果修改的是第一段或者最后一段则把直达里程修改
                if (mileageType==MileageType.start_after.getValue()||mileageType==MileageType.after_end.getValue()){
                    QueryWrapper<MileageEntity> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("route_id",mileage.getRouteId())
                            .eq("parent_id",-1L)
                             .eq("logic_delete", CommonConstants.LogicDelete.no_delet.getValue());
                    if (mileageType==MileageType.start_after.getValue()) {
                        queryWrapper.eq("from_id", mileageVo.getFromId());
                    }else{
                        queryWrapper.eq("to_id", mileageVo.getToId());
                    }
                    MileageEntity parent = this.baseMapper.selectOne(queryWrapper);
                    //如果左边边了
                    if (!left&&mileageType==MileageType.start_after.getValue()){
                        parent.setFromName(toStation.getStationName());
                        parent.setFromId(toStation.getStationId());
                    }
                    if (!right&&mileageType==MileageType.after_end.getValue()){
                        parent.setToName(fromStation.getStationName());
                        parent.setToId(fromStation.getStationId());

                    }
                    parent.setUpdateDate(new Date());
                    double sum = parent.getTotalMileage()+totalMileage;
                    parent.setTotalMileage(sum);
                    this.baseMapper.updateById(parent);
                }
            }
        }
    }

    @Override
    public void deleteMileageBatchByIds(List<Long> mileageIds) {

    }

    @Override
    public void deleteMileageByRouteId(List<Long> routeIds) {
        if (routeIds != null && routeIds.size() > 0) {
            this.baseMapper.deleteMileageByRouteIds(routeIds, CommonConstants.LogicDelete.delete.getValue());
        }
    }

    @Override
    public void deleteMieleageByStationId(Long stationId) {

    }

    @Override
    public ResponseData getAddParamters(Long mileageId) {
        List<StationEntity> stationList = stationService.queryAllStation(CommonConstants.LogicDelete.no_delet.getValue());
        List<RouteEntity> routeList = routeService.queryAllRoute(CommonConstants.LogicDelete.no_delet.getValue());
        MileageVo mileageVo = null;
        if (mileageId != null) {
            mileageVo = this.queryMileageVoByMileageId(mileageId, CommonConstants.LogicDelete.no_delet.getValue());
        }
        return ResponseData.ok().put("stationList", stationList).put("routeList", routeList).put("mileage", mileageVo);
    }

    @Override
    public MileageVo queryMileageVoByMileageId(Long mielageId, int logicDelete) {
        return this.baseMapper.queryMileageVoByMileageId(mielageId, logicDelete);
    }

    @Override
    public MileageEntity queryMileageByMileageId(Long mileageId, int logicDelete) {
        if (mileageId != null) {
            return this.baseMapper.queryMileageByMileageId(mileageId, logicDelete);
        }
        return null;
    }

    @Override
    public List<MileageEntity> queryAllMileage(int logicDelete) {
        return this.baseMapper.queryAllMileage(logicDelete);
    }
}
